/* 
 * File:   SyntacsFinder.cpp
 * Author: vicror
 * 
 * Created on December 13, 2011, 11:21 AM
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "SyntacsFinder.h"

namespace SearchEnginer {

    typedef unsigned char uchar;
#define cast(a) static_cast<uchar>(a)

    class Counter {
    public:
        Counter() {
            _index = -1;
            _count = 0;
            flag = false;
        }

        void inc() {
            _count++;
        }

        int count() {
            return _count;
        }

        Index index() {
            return _index;
        }

        bool setIndex(Index orig) {
            if (orig != _index) {
                bool temp=flag;
                _index = orig;
                resetCount();
                flag =true;
                return true & temp;
            } else {
                return false;
            }
        }

        void resetCount() {
            _count = 0;
        }

        bool operator<(const Counter& orig) const {
            return _count > orig._count;
        }

        Counter& operator++() {
            inc();
            return *this;
        }

        Counter operator++(int) {
            Counter temp=*this;
            inc();
            return temp;
        }
        
    private:
        bool flag;
        Index _index;
        int _count;
    };

    typedef std::vector<Counter> ListCounter;

    SyntacsFinder::SyntacsFinder():Base_SearchEnginer() {
    }

    SyntacsFinder::SyntacsFinder(const Base_SearchEnginer& orig)
       :Base_SearchEnginer(orig) {
        link(orig);
    }

    SyntacsFinder::~SyntacsFinder() {
    }

    void SyntacsFinder::syncWord(const string& orig,  Index index) {
            int step = -1;
            try {
                std::string::const_iterator one = orig.begin();
                std::string::const_iterator two = orig.begin();
                ++two;
                step++;
                while (one != orig.end()) {
                    uchar ch = 0;
                    if (two != orig.end()) ch = *two;
                    matrix[cast(*one)][ch].append(Item(index,step));
                    ++one;
                    ++two;
                    ++step;
                }
            }
            catch (std::bad_alloc) {
                if (step >=0) {
                    std::string::const_iterator one = orig.begin();
                    std::string::const_iterator two = orig.begin();
                    for(int i=0; i<step; i++) {
                        uchar ch = 0;
                        if (two != orig.end()) ch = *two;
                        matrix[cast(*one)][ch].remove(Item(index,i));
                        ++one;
                        ++two;
                    }
                }
            }
        }


    ListIndex SyntacsFinder::hasWordByID(const string& orig) const {
        Knot knot;
        std::string::const_iterator one = orig.begin();
        std::string::const_iterator two = orig.begin();
        if (one != orig.end()) {
            ++two;
            if (two != orig.end()) {
                knot.append(matrix[cast(*one)][cast(*two)]);
                ++one;
                ++two;
                while(two != orig.end()) {
                    knot.append(matrix[cast(*one)][cast(*two)]);
                    ++one;
                    ++two;
                }
            } else {
               for(int i=0; i < SizeBuf; i++) {
                   knot.append(matrix[cast(*one)][cast(i)]);
               }
            }
        }
        ListIndex temp;
        Knot::ListItemT item = knot.getItems();
        Counter counter;
        Counter Countertemp;
        ListCounter listCounter;
        for(Knot::ListItemTConstIter itr = item.begin(); itr != item.end(); ++itr) {
            Countertemp = counter;
            if (counter.setIndex((*itr).index())) {
                listCounter.push_back(Countertemp);
            }
            ++counter;
        }
        std::sort(listCounter.begin(), listCounter.end());
        for(ListCounter::iterator itr = listCounter.begin();
                itr != listCounter.end(); ++itr) {
            temp.push_back((*itr).index());
        }
        return temp;
    }

    void SyntacsFinder::OnClear() {
        for(int x = 0; x < SizeBuf; x++ ) {
            for(int y = 0; y <SizeBuf; y++) {
                matrix[cast(x)][cast(y)].clear();
            }
        }
    }


}


